<template>
    <el-row class="contain-box">
        <site-nav>&emsp;>&emsp;<strong><i>{{permissionName}}</i></strong></site-nav>
        <div class="view-body">
            <el-row>
                <el-form class="inline-form" inline>
                    <el-form-item>
                        <el-button @click="$router.go(-1)"><i class="el-icon-arrow-left el-icon--left"/>返回
                        </el-button>
                    </el-form-item>
                    <el-form-item>
                        <el-button :loading="submitting" @click="save" type="primary">保存</el-button>
                    </el-form-item>
                </el-form>
            </el-row>
            <el-row>
                <el-tree
                        :check-strictly="true"
                        :data="tree"
                        :default-checked-keys="defaultMenuIds"
                        :default-expand-all="true"
                        :expand-on-click-node="false"
                        :props="defaultProps"
                        @check="check"
                        @check-change="checkChange"
                        @node-click="nodeClick"
                        node-key="menuId"
                        ref="tree"
                        show-checkbox
                >
                </el-tree>
            </el-row>
        </div>
    </el-row>
</template>
<script lang="ts">
  import {ID} from '@/api/http';
  import MenuApi from '@/api/user/menuApi';
  import MenuPermissionApi from '@/api/user/menuPermissionApi';
  import Menu from '@/structure/menu';
  import {ElTree, TreeData, TreeNode, TreeProps} from 'element-ui/types/tree';
  import {Component, Vue} from 'vue-property-decorator';

  @Component
  export default class Page extends Vue {
    public defaultProps: TreeProps = {
      label: 'displayName',
      children: 'children',
      disabled: 'defaultMenu'
    } as TreeProps;
    public defaultMenuIds: ID[] = [];
    public permissionKey: string = '';
    public permissionName: string = '';
    public submitting: boolean = false;
    public tree: TreeData[] = [];

    public created(): void {
      this.permissionKey = this.$route.params.permissionKey;
      this.permissionName = this.$route.query.permissionName as string;

      MenuApi.tree().then((res) => {
        this.tree = res;
      });

      this.getDataList();
    }

    public getDataList(): void {
      MenuPermissionApi.find(this.permissionKey).then((res) => {
        (this.$refs.tree as ElTree<ID, Menu>).setCheckedKeys(this.defaultMenuIds.concat(res));
      });
    }

    public save(): void {
      const keys: ID[] = (this.$refs.tree as ElTree<ID, Menu>)
        .getCheckedNodes(false, true)
        .map((item) => (item as Menu).menuId);

      this.submitting = true;
      MenuPermissionApi
        .save(this.permissionKey, keys)
        .then(() => {
          this.submitting = false;
          this.$message.success('保存成功');
        })
        .catch(() => {
          this.submitting = false;
        });
    }

    public checkChange(data: Menu, checked: boolean): void {
      const tree = this.$refs.tree as ElTree<ID, Menu>;
      const node = tree.getNode(data);

      tree.setChecked(data, checked, false);

      if (!checked) {
        this.nodeUncheckedDeep(node, false);
      }
    }

    public check(data: Menu) {
      const tree = this.$refs.tree as ElTree<ID, Menu>;
      const node = tree.getNode(data);
      this.deep(node);
    }

    public nodeClick(obj: Menu, node: TreeNode<ID, Menu>) {
      node.checked = !node.checked;
      this.deep(node);
    }

    public deep(node: TreeNode<ID, Menu>) {
      this.nodeCheckedDeep(node, false, true);

      if (!node.checked) {
        this.nodeUncheckedDeep(node, false);
      }
    }

    public nodeCheckedDeep(node: TreeNode<ID, Menu>, parentValue: boolean, targetValue: boolean) {
      const parent = node.parent as TreeNode<ID, Menu>;
      if (parent && parent.checked === parentValue) {
        parent.checked = targetValue;
        this.nodeCheckedDeep(parent, parentValue, targetValue);
      }
    }

    public nodeUncheckedDeep(node: TreeNode<ID, Menu>, checked: boolean) {
      node.checked = false;
      if (node.childNodes) {
        node.childNodes.forEach((subNode) => this.nodeUncheckedDeep(subNode, checked));
      }
    }
  }
</script>
